#ifndef MIBS_H
#define MIBS_H
#include"basecipher.h"

#include <vector>
using namespace std ;

const int MIBS_BLOCK_SIZE = 64 ;
const int MIBS_ROUND = 32 ;
const int MIBS_SBOX_NUM = 16 ;
const int MIBS_KEY_NIBBLE = 8 ;
const int MIBS_WORD_NUM = 2 ;
const int MIBS_SBOX_SIZE = 4 ;
const int MIBS_INNER_NUM = 16 ;

const nibble MIBS_SBOX[MIBS_SBOX_NUM] = { 4 , 15 , 3 , 8 ,
                                           13 , 10 , 12 , 0 ,
                                           11 , 5 , 7 , 14 ,
                                           2 , 6 , 1 , 9 } ;
const int MIBS_P[MIBS_KEY_NIBBLE] = { 1 , 7 , 0 , 2 , 5 , 6 , 3 , 4 } ;

class MIBS :
    public BaseCipher
{
public:
    MIBS( const int BlockSize ,
              const int Round ,
              const int SboxSize ,
              const key_t InitialKey ,
              const plaintext_t Plaintext ,
              ciphertext_t& Ciphertext );
    ~MIBS(void);
    void Encryption(ciphertext_t& ciphertextvector) ;
    void Decryption() ;
    void print() ;

private:
    nibble RoundKey[MIBS_ROUND][MIBS_KEY_NIBBLE] ;
    nibble innerstate[MIBS_INNER_NUM] ;
    void mibs_keyxor( nibble in_key[] , nibble roundkey[] , const int array_num , nibble out_key[] ) ;
    void mibs_sbox( nibble in_sbox[] , const int array_num , nibble out_sbox[] ) ;
//	void mibs_xor( nibble in_xor[] , const int array_num , nibble out_xor[] ) ;
    void mibs_p( nibble in_p[] , const int array_num , nibble out_p[] ) ;
    void mibs_mix( nibble in_mix[] , const int array_num , nibble out_mix[] ) ;
    void KeySchedule( key_t InitialKey ) ;
    void OneRound( const int round ) ;
    void InvOneRound() ;
};

#endif // MIBS_H
